
<html id="calculator" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Calculator tutorial</title>
</head>
<body>
<!-- lz_content_start -->
<h1>Building a Calculator</h1>
<h2>Introduction</h2>
<p>In this section we draw on the concepts presented thus far to create a simple &#8212; calculator as shown below.</p>
 
<img src="img/d_t_calculator_1.jpg" alt="What the calculator will look like" width="121" height="180" border="0"/> 
 <p>As throughout this Guide, the examples are "live" and you can edit them. However, many of the examples are a bit long and not
ideally suited to the example editor.  So, if you wish to do some experimenting with this example you may wish to copy the source files
and resources to whichever directory you use for development.</p>
 
<p>All the art assets are <a href="./resources/calculator_tutorial.zip">here</a>.
For the purposes of this tutorial, place the art assets in the same folder that you are working in. </p>
<p>Keep in mind that this is an exercise in basic LZX, not in scripting, so there won't be too much discussion on how the script works.</p>

<h2>Visual Layout</h2>
<p>Our first step will be to build the calculator visually, that is not worry about the functionality; just make it look right. 
Let's start by bringing in all the art assets. There is a body, a display and a number of buttons. </p>

<example title="Using resource for body image" wrap="true" height="500" width="800">
&lt;canvas height="500" width="800"&gt;
    &lt;!-- fonts --&gt;
    &lt;font src="helmetbi.ttf" name="obliqueText" /&gt;
    &lt;font src="helmetr.ttf" name="displayText" /&gt;
    &lt;!-- art assets --&gt;
    &lt;resource name="calc_body" src="../resources/body.png" /&gt;
    &lt;resource name="calc_display" src="../resources/display.png" /&gt;
    &lt;resource name="button_grn" src="../resources/button_green.gif" /&gt;
    &lt;resource name="button_red" src="../resources/button_red.gif" /&gt;
    &lt;resource name="button_blu" src="../resources/button_blue.gif" /&gt;
    <span class="redText">&lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
    &lt;/view&gt;</span>
&lt;/canvas&gt;
</example>


<p>In this code we have brought in the fonts and art assets we plan to use, and created the body of the calculator. 
</p>
<p>We don't need to set the size of the view that is the calculator body, because it will stretch to the size of its resource automatically.</p>
 
<p>Next we add the display:</p>

<example title="Adding the display" wrap="true" width="800" height="500">
&lt;canvas width="800" height="500"&gt;
    &lt;!-- fonts --&gt;
    &lt;font src="helmetbi.ttf" name="obliqueText" /&gt;
    &lt;font src="helmetr.ttf" name="displayText" /&gt;
    &lt;!-- art assets --&gt;
    &lt;resource name="calc_body" src="../resources/body.png" /&gt;
    &lt;resource name="calc_display" src="../resources/display.png" /&gt;
    &lt;resource name="button_grn" src="../resources/button_green.gif" /&gt;
    &lt;resource name="button_red" src="../resources/button_red.gif" /&gt;
    &lt;resource name="button_blu" src="../resources/button_blue.gif" /&gt;
    
    &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
        &lt;!-- display --&gt;
        <span class="redText">&lt;view id="display" resource="calc_display" x="20" y="31"&gt;
            &lt;!-- the text in the display --&gt;
            &lt;text name="screen" height="30" width="165"
                  font="displayText" fontsize="30"
                  y="5" x="5"&gt;
                0
            &lt;/text&gt;
        &lt;/view&gt;</span>
    &lt;/view&gt;
&lt;/canvas&gt;
</example>


<p>There are two parts to this. The first is the light gray art asset that is the display itself, and the second is the text in the display.
 We're naming everything with <span class="code">name</span> attributes now, so that later we will be able to refer to these elements 
from scripts (e.g. change the text in the display).</p>
<p>Note that the <span class="code">text</span> tag is <i>within</i> the display <span class="code">view</span> tag. In fact it's 
convenient because it allows us to position the <span class="code">text</span> tag relative to the display, which is how we think of it.
</p>
    

<p>The buttons are all the same size, and they're arranged in a grid. The buttons are actually arranged in rows 
(or you might describe them as columns, but for the purposes of this tutorial, we're going to treat them as rows):</p>
 
<img src="img/d_t_calculator_2.gif" width="506" height="302" alt="How the calculator is broken down." border="0"/>
<p>Ignore the fact that the first row of two buttons is odd (we'll come to that later). The above diagram shows how we're going 
to arrange them. Each button will be a view with a resource attached to it. We could have used images
 for the labels, but it is far easier to use text.</p>
<p>Here's the code for a single button:</p>
<example title="code for a single button" extract="false">
    &lt;view resource="button_blu" clickable="true" 
          onclick="display.inputDigit( this );"&gt;
        &lt;text name="buttonText" font="obliqueText" fontsize="30" 
              fgcolor="#ffffff" x="9" valign="middle"&gt;
            7
        &lt;/text&gt;
    &lt;/view&gt;
</example>
<p>The <span class="code">resource</span> attribute tells the button what image to use. Remember the button will automatically size to 
fit the view. Next the <span class="code">clickable attribute</span> means that this button will be clickable - it will have 
an <span class="code">onclick</span> event, which will come to later and the mouse will change to a hand when it hovers over it. 
The <span class="code">text</span> tag is the button's label.</p>
<p>The <span class="code">onclick</span> event handler is calling a method that we haven't written yet.</p>
<p>The code for a row of buttons is as follows:</p>
<example title="code for a row of buttons" extract="false">
    &lt;!-- row 2 --&gt;
    &lt;view name="row2"&gt;
        <span class="redText">&lt;simplelayout axis="x" spacing="7" /&gt;</span>
        &lt;view resource="button_blu" clickable="true" 
              onclick="display.inputDigit( this );"&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="9" valign="middle"&gt;
                7
            &lt;/text&gt;
        &lt;/view&gt;
        &lt;view resource="button_blu" clickable="true" 
              onclick="display.inputDigit( this );"&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="9" valign="middle"&gt;
                8
            &lt;/text&gt;
        &lt;/view&gt;
        &lt;view resource="button_blu" clickable="true" 
              onclick="display.inputDigit( this );"&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="9" valign="middle"&gt;
                9
            &lt;/text&gt;
        &lt;/view&gt;
        &lt;view resource="button_blu" clickable="true" 
              onclick="display.inputDigit( this );"&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="9" valign="middle"&gt;
                *
            &lt;/text&gt;
        &lt;/view&gt;
    &lt;/view&gt;
</example>
<p>Notice that we're using the <span class="code">simplelayout</span> tag to control the spacing of the buttons <i>in the x-axis</i>.</p>
<p>For four rows of buttons, we will just repeat the above code, and we shall space all the <i>rows</i> with 
a <span class="code">simplelayout</span> <i>in the y-axis</i>. Here's the code so far:</p>

<example title="Spacing rows with &lt;simplelayout&gt;" width="800" height="500" wrap="true">
&lt;canvas  height="500" width="800"&gt;
    &lt;!-- fonts --&gt;
    &lt;font src="helmetbi.ttf" name="obliqueText" /&gt;
    &lt;font src="helmetr.ttf" name="displayText" /&gt;
    &lt;!-- art assets --&gt;
    &lt;resource name="calc_body" src="../resources/body.png" /&gt;
    &lt;resource name="calc_display" src="../resources/display.png" /&gt;
    &lt;resource name="button_grn" src="../resources/button_green.gif" /&gt;
    &lt;resource name="button_red" src="../resources/button_red.gif" /&gt;
    &lt;resource name="button_blu" src="../resources/button_blue.gif" /&gt;
    
    &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
        &lt;!-- display --&gt;
        &lt;view id="display" resource="calc_display" x="20" y="31"&gt;
            &lt;!-- the text in the display --&gt;
            &lt;text name="screen" height="30" width="165"
                  font="displayText" fontsize="30"
                  y="5" x="5"&gt;
                0
            &lt;/text&gt;
        &lt;/view&gt;
        &lt;!-- 5 rows of buttons --&gt;
        &lt;view name="buttons" x="19" y="88"&gt;
            <span class="redText">&lt;simplelayout axis="y" spacing="7" /&gt;</span>
            <span class="redText">&lt;!-- row 2 --&gt;</span>
            &lt;view name="row2"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        7
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        8
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        9
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        *
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            <span class="redText">&lt;!-- row 3 --&gt;</span>
            &lt;view name="row3"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        4
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        5
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        6
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="15" valign="middle"&gt;
                        -
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            <span class="redText">&lt;!-- row 4 --&gt;</span>
            &lt;view name="row4"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        1
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        2
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        3
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        +
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            <span class="redText">&lt;!-- row 5 --&gt;</span>
            &lt;view name="row5"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        0
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="20" 
                          fgcolor="#ffffff" x="5" valign="middle"&gt;
                        +/-
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        .
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_grn" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        =
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
        &lt;/view&gt;
    &lt;/view&gt;
&lt;/canvas&gt;
</example>


<p>The <span class="code">x</span> and <span class="code">fontsize</span> properties of the <span class="code">text</span> elements 
have been tweaked to get the button labels to line up correctly.</p>

<p>Finally, let's build the top row of buttons:</p>
<example title="top row of buttons" extract="false">
    &lt;!-- row 1 --&gt;
    &lt;view name="row1" <span class="redText">width="${parent.width}"</span>&gt;
        &lt;view resource="button_red" clickable="true" 
              onclick="display.inputDigit( this );"&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="7" valign="middle"&gt;
                C
            &lt;/text&gt;
        &lt;/view&gt;
        &lt;view resource="button_blu" clickable="true" 
              onclick="display.inputDigit( this );"
              <span class="redText">align="right"</span>&gt;
            &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                  fgcolor="#ffffff" x="9" valign="middle"&gt;
                /
            &lt;/text&gt;
        &lt;/view&gt;
    &lt;/view&gt;
</example>
<p>The "C" button will be automatically placed at <span class="code">x="0" y="0"</span>. The "/" button needs to be right aligned, hence 
the <span class="code">align="right"</span> attribute.</p>
<p>The <span class="code">parent</span> view of the buttons (i.e. one named <i>buttons</i> in the code above) will automatically size to 
fit rows 2, 3, 4 and 5, so it's OK to align the "/" button to the right, as long as we explicitly set the width of <i>row1</i> to the 
same as <i>buttons</i>.</p>
<a name="scripting"></a>
<h3>Scripting</h3>
<p>There is a lot of code here to make the calculator behave predictably. We can break this down into methods that perform tasks, 
and properties that retain values. Alternatively, if we didn't want to use methods and properties, we'd have to write a lot of 
functions and have a large number of global variables declared. All the methods that we write are going to be assigned to the
 <i>display</i> view, which is also the parent of the <i>screen</i> text field.</p>
<h4>Methods</h4>
<p>
<b>start()</b>
<br></br>
This is the method that sets up all the view properties.
</p>
<p>
<b>clear()</b>
<br></br>
For clearing the screen and restarting. All this does is call the start method again, so that the properties get re initialized. We could have called the start method directly when we wanted to clear the screen.
</p>
<p>
<b>inputDigit()</b>
<br></br>
The default method for hitting a key. This figures out what the user is typing in (whether it's a number, an operator, the equals
 sign and so forth) and takes the appropriate action.
</p>
<p>
<b>inputOperator()</b>
<br></br>
When the user hits an operator ("+", "-", "*", "/") a few things could based on what the user has entered previously. 
For example, if the user has hits "1" then "*", nothing happens. But if the user has already entered two operands 
and an operator (e.g. "1" then "*" then "4" <i>then</i> "+") the first expression gets evaluated. This method handles all that logic.
</p>
<p>
<b>equals()</b>
<br></br>
Called when the user hits the equals sign. </p>
<p>
<b>execute()</b>
<br></br>
The actual method that does any computation. Called from various circumstances.</p>
<p>
<b>isThereDecimal()</b>
<br></br>
Utility method for checking if a decimal point is shown on the display (to prevent one from being entered twice.</p>
<p>
<b>addDecimalPoint()</b>
<br></br>
Concatenates a decimal point to the end of the display</p>
<b>negative()</b>
<h4>Properties</h4>
<p>
<b>valueX</b>
<br></br>
The first operand (value) to use.</p>
<p>
<b>oldValue</b>
<br></br>
This can be different things depending on the combination of buttons that were entered.</p>
<p>
<b>lastInput</b>
<br></br>
What was last entered (e.g. digit, equals, operator).</p>
<p>
<b>allOperators</b>
<br></br>
An array of values that are operators.</p>
<p>
<b>operator</b>
<br></br>
The active operator (e.g. "+").</p>
<h4>Global functions</h4>
<p>
<b>isInArray</b>
<br></br>
This is a simple function that loops through an array to determine whether a value is contained within it. 
The reason it is not a method is because it's the kind of function that might be reused in another script, and it's handy to have 
it set aside like this.</p>
<p>So here's the full code:</p>

<example title="Completed calculator" height="500" width="800" wrap="true">
&lt;canvas  height="500" width="800"&gt;
    &lt;!-- fonts --&gt;
    &lt;font src="helmetbi.ttf" name="obliqueText" /&gt;
    &lt;font src="helmetr.ttf" name="displayText" /&gt;
    &lt;!-- art assets --&gt;
    &lt;resource name="calc_body" src="../resources/body.png" /&gt;
    &lt;resource name="calc_display" src="../resources/display.png" /&gt;
    &lt;resource name="button_grn" src="../resources/button_green.gif" /&gt;
    &lt;resource name="button_red" src="../resources/button_red.gif" /&gt;
    &lt;resource name="button_blu" src="../resources/button_blue.gif" /&gt;
    
    &lt;!-- global variables and functions --&gt;
    &lt;script&gt;
    &lt;![CDATA[
        // utility function that finds an item in an array
        //
        function isInArray( x, theArray ) {
            var isThere = false;
            for ( var i=0; i&lt;theArray.length; i++ ) {
                if ( theArray[i] == x ) {
                    isThere = true;
                }
            }
            return isThere;
        }
    ]]&gt;
    &lt;/script&gt;
    &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
        &lt;!-- display --&gt;
        &lt;view id="display" resource="calc_display" x="20" y="31"
              oninit="this.start()"&gt;
            &lt;!-- the text in the display --&gt;
            &lt;text name="screen" height="30" width="165"
                  font="displayText" fontsize="30"
                  y="5" x="5"&gt;
                0
            &lt;/text&gt;
            &lt;method name="start"&gt;
                this.valueX = 0;
                this.lastInput = 'none';
                this.oldValue = false;
                this.allOperators = new Array( '+', '-', '/', '*' );
                this.operator = '+';
                this.screen.setText( this.valueX.toString() );
            &lt;/method&gt;
           
            &lt;method name="clear"&gt;
                this.start();
            &lt;/method&gt;
            &lt;!-- handles the push of a button --&gt;
            &lt;method name="inputDigit" args="buttonObj"&gt;
            &lt;![CDATA[
                var val = buttonObj.buttonText.getText();
                // weed out any non-numbers (e.g. operators, clear button)
                if ( isInArray( val, this.allOperators ) ) {
                    var theOperator = val;
                    this.inputOperator( theOperator );
                    return;
                } else if ( val == 'C' ) {
                    this.start();
                    return;
                } else if ( val == '.' ) {
                    this.addDecimalPoint();
                    return;
                } else if ( val == '+/-' ) {
                    this.negative();
                    return;
                } else if ( val == '=' ) {
                    this.equals();
                    return;
                }
                displ = this.screen.getText();
                if ( ( displ == '0' ) &amp;&amp; ( val == '0' ) ) {
                    return;
                }
                if ( ( this.lastInput == 'none' ) 
                    || ( this.lastInput == 'operator' ) ) {
                    // clear display and rewrite
                    this.screen.setText( val );    
                } else if ( this.lastInput == 'digit' ) {
                    this.screen.setText( displ + val );
                } else if ( this.lastInput == 'equals' ) {
                    this.clear();
                    this.screen.setText( val );
                }
                this.lastInput = 'digit';
            ]]&gt;
            &lt;/method&gt;
            &lt;method name="inputOperator" args="operator"&gt;
                if ( this.lastInput == 'digit' ) {
                    this.execute( this.screen.getText() );
                }
                this.valueX = this.screen.getText();
                this.operator = operator;
                this.lastInput = 'operator';
            &lt;/method&gt;
            &lt;method name="equals"&gt;
                if (this.lastInput != 'equals' ) {
                    this.oldValue = this.screen.getText();
                    this.lastInput = 'equals';
                    this.execute( this.oldValue );
                } else {
                    this.lastInput = 'equals';
                    this.execute( this.oldValue );
                }
            &lt;/method&gt;
            &lt;method name="execute" args="val"&gt;
                this.valueX -= 0;
                var valFromDisp = val - 0;
                if ( this.valueX == 0 ) return;
                if ( this.operator == '+' ) {
                    val = this.valueX + valFromDisp;
                } else if ( this.operator == '-' ) {
                    val = this.valueX - valFromDisp;
                } else if ( this.operator == '*' ) {
                    val = this.valueX * valFromDisp;
                } else if ( this.operator == '/' ) {
                    val = this.valueX / valFromDisp;
                }
                valFromDisp = val;
                this.screen.setText( valFromDisp.toString() );
                this.valueX = this.screen.getText();
            &lt;/method&gt;
            &lt;method name="isThereDecimal"&gt;
            &lt;![CDATA[
                var disp = this.screen.getText();
                var isDecimal = false;
                for ( var i=0; i&lt;disp.length; i++ ) {
                    if ( disp.charAt( i ) == '.' ) {
                        return true;
                    }
                }
                return false;
            ]]&gt;
            &lt;/method&gt;
            
            &lt;method name="addDecimalPoint"&gt;
                if ( ( this.lastInput == 'none' ) 
                   || ( this.lastInput == 'operator' ) ) {
                    if ( !this.isThereDecimal() ) {
                        this.screen.setText( "0." );
                    }
                } else if ( this.lastInput == 'digit' ) {
                    if ( !this.isThereDecimal() ) {
                        var newText = this.screen.getText();
                        newText += ".";
                        this.screen.setText( newText );
                    }
                } else if ( this.lastInput == 'equals' ) {
                    this.clear(); 
                    this.screen.setText( '0.' );
                }
                this.lastInput = 'digit';
            &lt;/method&gt;
            
            &lt;method name="negative"&gt;
                if ( ( this.lastInput == 'digit' ) ||
                    ( this.lastInput == 'equals' ) ) {
                    var newDisp = ( this.screen.getText() - 0 ) * -1;
                    this.screen.setText( newDisp.toString() ); 
                } else {
                    clear();
                }            
            &lt;/method&gt;
        &lt;/view&gt;
        &lt;!-- 5 rows of buttons --&gt;
        &lt;view name="buttons" x="19" y="88"&gt;
            &lt;simplelayout axis="y" spacing="7" /&gt;
            &lt;!-- row 1 --&gt;
            &lt;view name="row1" width="${parent.width}"&gt;
                &lt;view resource="button_red" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="7" valign="middle"&gt;
                        C
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"
                      align="right"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        /
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            &lt;!-- row 2 --&gt;
            &lt;view name="row2"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        7
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        8
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        9
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        *
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            &lt;!-- row 3 --&gt;
            &lt;view name="row3"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        4
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        5
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        6
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="15" valign="middle"&gt;
                        -
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            &lt;!-- row 4 --&gt;
            &lt;view name="row4"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        1
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        2
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        3
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        +
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
            &lt;!-- row 5 --&gt;
            &lt;view name="row5"&gt;
                &lt;simplelayout axis="x" spacing="7" /&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        0
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="20" 
                          fgcolor="#ffffff" x="5" valign="middle"&gt;
                        +/-
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_blu" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        .
                    &lt;/text&gt;
                &lt;/view&gt;
                &lt;view resource="button_grn" clickable="true" 
                      onclick="display.inputDigit( this );"&gt;
                    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
                          fgcolor="#ffffff" x="9" valign="middle"&gt;
                        =
                    &lt;/text&gt;
                &lt;/view&gt;
            &lt;/view&gt;
        &lt;/view&gt;
    &lt;/view&gt;
&lt;/canvas&gt;
</example>

<p>Notice that there is now an <span class="code">oninit</span> event handler on the display that calls the <i>start</i> method.</p>
<p>Also notice how we're always calling the <i>inputDigit</i> method from the buttons with the same argument: We're passing 
the button element, and the <i>inputDigit</i> method works out what the button it is by calling the getText() method on its
 text element. This saves us the hassle of writing a different argument each time.</p>
 
<p>There is still a lot of code here, a lot of which is repetitive. We can condense it by using
  <a href="classes.html">classes</a>.</p>
<h2><a name="perspective"></a>Using Classes to Simplify</h2>
<p>That is a perfect candidate for the use of classes.</p>
<todo>
need another intro sentence
</todo>
<h3>Button</h3>
<p>Consider a calculator button. Most of them are blue and they have a white label on them. The label varies from button to button. They all call a method when clicked. When we say blue, we really mean that they take a resource which happens to be blue. Some buttons take other images. In at least one case, we had to position the label explicitly so it would look right.</p>
<p>In short, what we need is a class that will:</p>
<ul>
  <li>Produce a blue button by default.</li>
  <li>Allow us to specify a different resource.</li>
  <li>Take a label attribute.</li>
  <li>Allow the label to be explicitly positioned in the x plane to tweak it.</li>
</ul>
<p>Here is the old code for a single button:</p>
<example title="Single button">
&lt;canvas width="800" height="80"&gt;
  &lt;!-- fonts --&gt;
  &lt;font src="helmetbi.ttf" name="obliqueText"/&gt;
  
  &lt;!-- art assets --&gt;
  &lt;resource name="button_blu" src="../resources/button_blue.gif"/&gt;
  
  
  <em>&lt;view resource="button_blu" clickable="true" 
        onclick="display.inputDigit(this);"&gt;
    &lt;text name="buttonText" font="obliqueText" fontsize="30" 
          fgcolor="#ffffff" x="9" valign="middle"&gt;
      0
    &lt;/text&gt;
  &lt;/view&gt;</em>
&lt;/canvas&gt;
</example>
<p>And here's how that might be translated into a class:</p>
<example title="Converting button to class">
&lt;canvas width="800" height="100"&gt;
  &lt;font src="helmetbi.ttf" name="obliqueText"/&gt;
  &lt;resource name="button_blu" src="../resources/button_blue.gif"/&gt;
  &lt;resource name="button_red" src="../resources/button_red.gif"/&gt;
  &lt;resource name="button_green" src="../resources/button_green.gif"/&gt;
  
  &lt;class name="calcButton" resource="button_blu" clickable="true" 
           onclick="display.inputDigit(this);" oninit="this.initButton()"&gt;
    &lt;attribute name="buttLabel" type="string"/&gt;
    &lt;attribute name="labelX" type="number" value="11"/&gt;
    
    &lt;method name="initButton"&gt;
      this.buttonText.setAttribute('x', 
                                   this.getAttribute('labelX'));
      this.buttonText.setText(this.getAttribute('buttLabel'));
    &lt;/method&gt;
    
    &lt;text name="buttonText" font="obliqueText" fontsize="25" 
              fgcolor="#ffffff" x="13" valign="middle"&gt;
      &lt;method event="ontext"&gt;
        this.setAttribute('width', this.getTextWidth() + 5);
      &lt;/method&gt;
    &lt;/text&gt;
  &lt;/class&gt;
  
  &lt;simplelayout axis="x" spacing="5"/&gt;
  &lt;calcButton buttLabel="0"/&gt;
  &lt;calcButton buttLabel="1" resource="button_red"/&gt;
  &lt;calcButton buttLabel="+/-" resource="button_green" labelX="0"/&gt;
&lt;/canvas&gt;
</example>
<p>We can give the class a default resource (<varname>button_blu</varname>), as well as a default onclick attribute. Since these are 
default attributes of the class we're extending (i.e. view), they get overwritten when we instantiate the class and set that attribute.
 However we need a method to handle the custom attributes <attribute>buttLabel</attribute> and <attribute>labelX</attribute>. That's why 
we call the <method>initButton</method> method at init time, and set the label of the text and optionally the x-offset of the label 
that way.</p>
<todo>mention why I didn't use the method event="" syntax here</todo>
<p>In this case we've made the fontsize of the view a little smaller, so that we don't have to worry about making the labels fit 
the buttons.</p>
<p>The method within the <tagname>text</tagname> tag adjusts the size of the text field when the text gets set to the correct size 
(plus a few extra pixels for good measure).</p>
<p>Applying this to the original calculator code, we get:</p>
<example title="Classes in calculator">
&lt;canvas width="800" height="400"&gt;
  &lt;!-- fonts --&gt;
  &lt;font src="helmetbi.ttf" name="obliqueText"/&gt;
  &lt;font src="helmetr.ttf" name="displayText"/&gt;
  
  &lt;!-- art assets --&gt;
  &lt;resource name="calc_body" src="../resources/body.png"/&gt;
  &lt;resource name="calc_display" src="../resources/display.png"/&gt;
  &lt;resource name="button_grn" src="../resources/button_green.gif"/&gt;
  &lt;resource name="button_red" src="../resources/button_red.gif"/&gt;
  &lt;resource name="button_blu" src="../resources/button_blue.gif"/&gt;
  
  <em>&lt;!-- classes --&gt;
  &lt;class name="calcButton" resource="button_blu" clickable="true" 
          onclick="display.inputDigit(this);" oninit="this.initButton()"&gt;
    &lt;attribute name="buttLabel" type="string"/&gt;
    &lt;attribute name="labelX" type="number" value="11"/&gt;
    
    &lt;method name="initButton"&gt;
      this.buttonText.setAttribute('x', 
                                   this.getAttribute('labelX'));
      this.buttonText.setText(this.getAttribute('buttLabel'));
    &lt;/method&gt;
        
    &lt;text name="buttonText" font="obliqueText" fontsize="25" 
              fgcolor="#ffffff" x="13" valign="middle" width="0"&gt;
      &lt;method event="ontext"&gt;
        this.setAttribute('width', this.getTextWidth() + 5);
      &lt;/method&gt;
    &lt;/text&gt;
  &lt;/class&gt;</em>
  
  &lt;!-- global variables and functions --&gt;
  &lt;script&gt;&lt;![CDATA[
    // utility function that finds an item in an array
    //
    function isInArray(x, theArray) {
      var isThere = false;
        for (var i=0; i&lt;theArray.length; i++) {
          if (theArray[i] == x) {
            isThere = true;
          }
        }
      return isThere;
    }
    ]]&gt;&lt;/script&gt;
    
  &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
    &lt;!-- display --&gt;
    &lt;view id="display" resource="calc_display" x="20" y="31"
          oninit="this.start()"&gt;
      &lt;!-- the text in the display --&gt;
      &lt;text name="screen" height="30" width="165"
            font="displayText" fontsize="30"
            y="5" x="5"&gt;
        0
      &lt;/text&gt;
      
      &lt;method name="start"&gt;
        this.valueX = 0;
        this.lastInput = 'none';
        this.oldValue = false;
        this.allOperators = new array('+', '-', '/', '*');
        this.operator = '+';
        this.screen.setText(this.valueX.toString());
      &lt;/method&gt;
      
      &lt;method name="clear"&gt;
        this.start();
      &lt;/method&gt;
      
      &lt;!-- handles the push of a button --&gt;
      &lt;method name="inputDigit" args="buttonObj"&gt;
      &lt;![CDATA[
        var val = buttonObj.buttonText.getText();
        
        // weed out any non-numbers (e.g. operators, clear button)
        if (isInArray(val, this.allOperators)) {
          var theOperator = val;
          this.inputOperator(theOperator);
          return;
        } else if (val == 'C') {
          this.start();
          return;
        } else if (val == '.') {
          this.addDecimalPoint();
          return;
        } else if (val == '+/-') {
          this.negative();
          return;
        } else if (val == '=') {
          this.equals();
          return;
        }
        
        displ = this.screen.getText();
       if (displ == 0) { 
           if (val == 0) {
           return;
           }
        }
        
        if ((this.lastInput == 'none') 
            || (this.lastInput == 'operator')) {
          // clear display and rewrite
          this.screen.setText(val);    
        } else if (this.lastInput == 'digit') {
          this.screen.setText(displ + val);
        } else if (this.lastInput == 'equals') {
          this.clear();
          this.screen.setText(val);
        }
        this.lastInput = 'digit';
        ]]&gt;
      &lt;/method&gt;
      
      &lt;method name="inputOperator" args="operator"&gt;
        if (this.lastInput == 'digit') {
          this.execute(this.screen.getText());
        }
        this.valueX = this.screen.getText();
        this.operator = operator;
        this.lastInput = 'operator';
      &lt;/method&gt;
      
      &lt;method name="equals"&gt;
        if (this.lastInput != 'equals') {
          this.oldValue = this.screen.getText();
          this.lastInput = 'equals';
          this.execute(this.oldValue);
        } else {
          this.lastInput = 'equals';
          this.execute(this.oldValue);
        }
      &lt;/method&gt;
      
      &lt;method name="execute" args="val"&gt;
        this.valueX -= 0;
        var valFromDisp = val - 0;
        if (this.valueX == 0) return;
        
        if (this.operator == '+') {
          val = this.valueX + valFromDisp;
        } else if (this.operator == '-') {
          val = this.valueX - valFromDisp;
        } else if (this.operator == '*') {
          val = this.valueX * valFromDisp;
        } else if (this.operator == '/') {
          val = this.valueX / valFromDisp;
        }
        valFromDisp = val;
        this.screen.setText(valFromDisp.toString());
        this.valueX = this.screen.getText();
      &lt;/method&gt;
      
      &lt;method name="isThereDecimal"&gt;
      &lt;![CDATA[
        var disp = this.screen.getText();
        var isDecimal = false;
        for (var i=0; i != disp.length; i++) {
          if (disp.charAt(i) == '.') {
            return true;
          }
        }
        return false;
        ]]&gt;
      &lt;/method&gt;
      
      &lt;method name="addDecimalPoint"&gt;
        if ((this.lastInput == 'none') 
             || (this.lastInput == 'operator')) {
          if (!this.isThereDecimal()) {
            this.screen.setText("0.");
          }
        } else if (this.lastInput == 'digit') {
          if (!this.isThereDecimal()) {
            var newText = this.screen.getText();
            newText += ".";
            this.screen.setText(newText);
          }
        } else if (this.lastInput == 'equals') {
          this.clear(); 
          this.screen.setText('0.');
        }
        this.lastInput = 'digit';
      &lt;/method&gt;
      
      &lt;method name="negative"&gt;
        if ((this.lastInput == 'digit') ||
            (this.lastInput == 'equals')) {
          var newDisp = (this.screen.getText() - 0) * -1;
          this.screen.setText(newDisp.toString()); 
        } else {
          clear();
        }            
      &lt;/method&gt;
    &lt;/view&gt;
    
    &lt;!-- 5 rows of buttons --&gt;
    &lt;view name="buttons" x="19" y="88"&gt;
      &lt;simplelayout axis="y" spacing="7"/&gt;
      &lt;!-- row 1 --&gt;
      &lt;view name="row1" width="100%"&gt;
        &lt;calcButton buttLabel="C" resource="button_red"/&gt;
        &lt;calcButton buttLabel="/" align="right" labelX="13"/&gt;
      &lt;/view&gt;
      
      &lt;!-- row 2 --&gt;
      &lt;view name="row2"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        <em>&lt;calcButton buttLabel="7"/&gt;
        &lt;calcButton buttLabel="8"/&gt;
        &lt;calcButton buttLabel="9"/&gt;
        &lt;calcButton buttLabel="*" labelX="13"/&gt;</em>
      &lt;/view&gt;
       &lt;!-- row 3 --&gt;
      &lt;view name="row3"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        <em>&lt;calcButton buttLabel="4"/&gt;
        &lt;calcButton buttLabel="5"/&gt;
        &lt;calcButton buttLabel="6"/&gt;
        &lt;calcButton buttLabel="-" labelX="15"/&gt;</em>
      &lt;/view&gt;
      
      &lt;!-- row 4 --&gt;
      &lt;view name="row4"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        <em>&lt;calcButton buttLabel="1"/&gt;
        &lt;calcButton buttLabel="2"/&gt;
        &lt;calcButton buttLabel="3"/&gt;
        &lt;calcButton buttLabel="+"/&gt;</em>
      &lt;/view&gt;
       &lt;!-- row 5 --&gt;
      &lt;view name="row5"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        <em>&lt;calcButton buttLabel="0"/&gt;
        &lt;calcButton buttLabel="+/-" labelX="1"/&gt;
        &lt;calcButton buttLabel="." labelX="16"/&gt;
        &lt;calcButton buttLabel="=" resource="button_grn" labelX="12"/&gt;</em>
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>Not only does this make the code more navigable, but lightens the calculator app by over 100 lines of code.</p>
<p>Now say that we wanted to upgrade the buttons we have and make them react to mouse events (e.g. highlight when rolled over
and appear depressed when clicked). Since we've created a class, we only have to make the change in one place, and it will 
immediately be propagated to all of the instances of that class:</p>
<example title="Updating class definition">
&lt;canvas width="800" height="400"&gt;
  &lt;!-- fonts --&gt;
  &lt;font src="helmetbi.ttf" name="obliqueText"/&gt;
  &lt;font src="helmetr.ttf" name="displayText"/&gt;
  
  &lt;!-- art assets --&gt;
  &lt;resource name="calc_body" src="../resources/body.png"/&gt;
  &lt;resource name="calc_display" src="../resources/display.png"/&gt;
  <em>&lt;resource name="button_grn"&gt;
    &lt;frame src="../resources/new_button_green_off.png"/&gt;
    &lt;frame src="../resources/new_button_green_over.png"/&gt;
    &lt;frame src="../resources/new_button_green_down.png"/&gt;
  &lt;/resource&gt;
  &lt;resource name="button_blu"&gt;
    &lt;frame src="../resources/new_button_blue_off.png"/&gt;
    &lt;frame src="../resources/new_button_blue_over.png"/&gt;
    &lt;frame src="../resources/new_button_blue_down.png"/&gt;
  &lt;/resource&gt;
  &lt;resource name="button_red"&gt;
    &lt;frame src="../resources/new_button_red_off.png"/&gt;
    &lt;frame src="../resources/new_button_red_over.png"/&gt;
    &lt;frame src="../resources/new_button_red_down.png"/&gt;
  &lt;/resource&gt;</em>
  
  &lt;!-- classes --&gt;
  &lt;class name="calcButton" resource="button_blu" clickable="true" 
          onclick="display.inputDigit(this);" oninit="this.initButton()"
          <em>extends="basebutton"</em>&gt;
    &lt;attribute name="buttLabel" type="string"/&gt;
    &lt;attribute name="labelX" type="number" value="11"/&gt;
    
    &lt;method name="initButton"&gt;
      this.buttonText.setAttribute('x', 
                                   this.getAttribute('labelX'));
      this.buttonText.setText(this.getAttribute('buttLabel'));
    &lt;/method&gt;
        
    &lt;text name="buttonText" font="obliqueText" fontsize="25" 
          fgcolor="#ffffff" x="13" valign="middle" width="0"&gt;
      &lt;method event="ontext"&gt;
        this.setAttribute('width', this.getTextWidth() + 5);
      &lt;/method&gt;
    &lt;/text&gt;
  &lt;/class&gt;
  
  &lt;!-- global variables and functions --&gt;
  &lt;script&gt;
  &lt;![CDATA[
    // utility function that finds an item in an array
    //
    function isInArray(x, theArray) {
      var isThere = false;
      for (var i=0; i != theArray.length; i++) {
        if (theArray[i] == x) {
          isThere = true;
        }
      }
      return isThere;
    }
  ]]&gt;
  &lt;/script&gt;
  
  &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
    &lt;!-- display --&gt;
    &lt;view id="display" resource="calc_display" x="20" y="31"
              oninit="this.start()"&gt;
      &lt;!-- the text in the display --&gt;
      &lt;text name="screen" height="30" width="165"
                  font="displayText" fontsize="30"
                  y="5" x="5"&gt;
                0
      &lt;/text&gt;
      
      &lt;method name="start"&gt;
        this.valueX = 0;
        this.lastInput = 'none';
        this.oldValue = false;
        this.allOperators = new array('+', '-', '/', '*');
        this.operator = '+';
        this.screen.setText(this.valueX.toString());
      &lt;/method&gt;
      
      &lt;method name="clear"&gt;
        this.start();
      &lt;/method&gt;
      
      &lt;!-- handles the push of a button --&gt;
      &lt;method name="inputDigit" args="buttonObj"&gt;
      &lt;![CDATA[
        var val = buttonObj.buttonText.getText();
        // weed out any non-numbers (e.g. operators, clear button)
        if (isInArray(val, this.allOperators)) {
          var theOperator = val;
          this.inputOperator(theOperator);
          return;
        } else if (val == 'C') {
          this.start();
          return;
        } else if (val == '.') {
          this.addDecimalPoint();
          return;
        } else if (val == '+/-') {
          this.negative();
          return;
        } else if (val == '=') {
          this.equals();
          return;
        }
 
        displ = this.screen.getText();
        if  (displ == '0') { if (val == '0') {  
          return;
          }
        }
 
        if ((this.lastInput == 'none') 
            || (this.lastInput == 'operator')) {
            // clear display and rewrite
          this.screen.setText(val);    
        } else if (this.lastInput == 'digit') {
          this.screen.setText(displ + val);
        } else if (this.lastInput == 'equals') {
          this.clear();
          this.screen.setText(val);
        }
        this.lastInput = 'digit';
      ]]&gt;
      &lt;/method&gt;
            
      &lt;method name="inputOperator" args="operator"&gt;
        if (this.lastInput == 'digit') {
          this.execute(this.screen.getText());
        }
        this.valueX = this.screen.getText();
        this.operator = operator;
        this.lastInput = 'operator';
      &lt;/method&gt;
      &lt;method name="equals"&gt;
        if (this.lastInput != 'equals') {
          this.oldValue = this.screen.getText();
          this.lastInput = 'equals';
          this.execute(this.oldValue);
        } else {
          this.lastInput = 'equals';
          this.execute(this.oldValue);
        }
      &lt;/method&gt;
      &lt;method name="execute" args="val"&gt;
        this.valueX -= 0;
        var valFromDisp = val - 0;
        if (this.valueX == 0) return;
        if (this.operator == '+') {
          val = this.valueX + valFromDisp;
        } else if (this.operator == '-') {
          val = this.valueX - valFromDisp;
        } else if (this.operator == '*') {
          val = this.valueX * valFromDisp;
        } else if (this.operator == '/') {
          val = this.valueX / valFromDisp;
        }
        valFromDisp = val;
        this.screen.setText(valFromDisp.toString());
        this.valueX = this.screen.getText();
      &lt;/method&gt;
      &lt;method name="isThereDecimal"&gt;
      &lt;![CDATA[
        var disp = this.screen.getText();
        var isDecimal = false;
        for (var i=0; i !=disp.length; i++) {
          if (disp.charAt(i) == '.') {
            return true;
          }
        }
        return false;
      ]]&gt;
      &lt;/method&gt;
      &lt;method name="addDecimalPoint"&gt;
        if ((this.lastInput == 'none') 
           || (this.lastInput == 'operator')) {
          if (!this.isThereDecimal()) {
              this.screen.setText("0.");
          }
        } else if (this.lastInput == 'digit') {
          if (!this.isThereDecimal()) {
            var newText = this.screen.getText();
            newText += ".";
            this.screen.setText(newText);
          }
        } else if (this.lastInput == 'equals') {
          this.clear(); 
          this.screen.setText('0.');
        }
        this.lastInput = 'digit';
      &lt;/method&gt;
      &lt;method name="negative"&gt;
        if ((this.lastInput == 'digit') ||
            (this.lastInput == 'equals')) {
          var newDisp = (this.screen.getText() - 0) * -1;
          this.screen.setText(newDisp.toString()); 
        } else {
          clear();
        }            
      &lt;/method&gt;
    &lt;/view&gt;
    
    &lt;!-- 5 rows of buttons --&gt;
    &lt;view name="buttons" x="19" y="88"&gt;
      &lt;simplelayout axis="y" spacing="7"/&gt;
      &lt;!-- row 1 --&gt;
      &lt;view name="row1" width="100%"&gt;
        &lt;calcButton buttLabel="C" resource="button_red"/&gt;
        &lt;calcButton buttLabel="/" align="right" labelX="13"/&gt;
      &lt;/view&gt;
      &lt;!-- row 2 --&gt;
      &lt;view name="row2"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        &lt;calcButton buttLabel="7"/&gt;
        &lt;calcButton buttLabel="8"/&gt;
        &lt;calcButton buttLabel="9"/&gt;
        &lt;calcButton buttLabel="*" labelX="13"/&gt;
      &lt;/view&gt;
      &lt;!-- row 3 --&gt;
      &lt;view name="row3"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        &lt;calcButton buttLabel="4"/&gt;
        &lt;calcButton buttLabel="5"/&gt;
        &lt;calcButton buttLabel="6"/&gt;
        &lt;calcButton buttLabel="-" labelX="15"/&gt;
      &lt;/view&gt;
      &lt;!-- row 4 --&gt;
      &lt;view name="row4"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        &lt;calcButton buttLabel="1"/&gt;
        &lt;calcButton buttLabel="2"/&gt;
        &lt;calcButton buttLabel="3"/&gt;
        &lt;calcButton buttLabel="+"/&gt;
      &lt;/view&gt;
      &lt;!-- row 5 --&gt;
      &lt;view name="row5"&gt;
        &lt;simplelayout axis="x" spacing="7"/&gt;
        &lt;calcButton buttLabel="0"/&gt;
        &lt;calcButton buttLabel="+/-" labelX="1"/&gt;
        &lt;calcButton buttLabel="." labelX="16"/&gt;
        &lt;calcButton buttLabel="=" resource="button_grn" labelX="12"/&gt;
      &lt;/view&gt;
    &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>Aside from defining and naming the new multi-frame resources at the
top of the code, the only other change was to extend the
<classname>basebutton</classname> class instead of the
<classname>LzView</classname> class. The
<classname>basebutton</classname> class is a predefined class that
gives simple mouse rollover and click behavior to a view with a
multiframe resource. Since the <classname>basebutton</classname> class
extends <classname>LzView</classname>, it inherits all
<classname>LzView</classname>'s attributes. This means that we can
still use the same attributes (e.g. <attribute>onclick</attribute> and
<attribute>resource</attribute>) in our new <classname
link="false">calcButton</classname> class, as we could in the original
<tagname>view</tagname> tag, which used to <em>be</em> the button.</p>
<h2><a name="separating"></a>Separating Across Files</h2>
<p>Although we've saved a lot of typing, the lzx file is still quite long. This may not be much of an issue if 
you're writing this application on your own, but one of the great advantages of using classes is that a project can be 
divided up among developers with ease. To do this, we're going to break the calculator application across a number of files, 
using classes as a divider.</p>
<p>Since we already have the button separated out as a class, let's start with that one:</p>
<example extract="false" title="Grouping classes in libraries">
<b>calculator_button.lzx:</b>
<em>&lt;library&gt;</em>
  &lt;!-- A standard calculator button --&gt;
  &lt;resource name="button_grn"&gt;
    &lt;frame src="./resources/new_button_green_off.png"/&gt;
    &lt;frame src="./resources/new_button_green_over.png"/&gt;
    &lt;frame src="./resources/new_button_green_down.png"/&gt;
  &lt;/resource&gt;
  &lt;resource name="button_blu"&gt;
    &lt;frame src="./resources/new_button_blue_off.png"/&gt;
    &lt;frame src="./resources/new_button_blue_over.png"/&gt;
    &lt;frame src="./resources/new_button_blue_down.png"/&gt;
  &lt;/resource&gt;
  &lt;resource name="button_red"&gt;
    &lt;frame src="./resources/new_button_red_off.png"/&gt;
    &lt;frame src="./resources/new_button_red_over.png"/&gt;
    &lt;frame src="./resources/new_button_red_down.png"/&gt;
  &lt;/resource&gt;
  
  &lt;class name="calcButton" resource="button_blu" clickable="true" 
          onclick="display.inputDigit(this);" oninit="this.initButton()"
          extends="basebutton"&gt;
    &lt;attribute name="buttLabel" type="string"&gt;
    &lt;attribute name="labelX" type="number" value="11"&gt;
    
    &lt;method name="initButton"&gt;
      this.buttonText.setAttribute('x', 
                                   this.getAttribute('labelX'));
      this.buttonText.setText(this.getAttribute('buttLabel'));
    &lt;/method&gt;
    
    &lt;text name="buttonText" font="obliqueText" fontsize="25" 
              fgcolor="#ffffff" x="13" valign="middle"&gt;
      &lt;method event="ontext"&gt;
        this.setAttribute('width', this.getTextWidth() + 5);
      &lt;/method&gt;
    &lt;/text&gt;
  &lt;/class&gt;
<em>&lt;/library&gt;</em>
</example>
<p>Notice that the <tagname>library</tagname> tag replaces the <tagname>canvas</tagname> when we're breaking apart code like this. 
It's also worth noting that the resources included by calculator_button.lzx are referenced <i>relative</i> to it.</p>
<p>Next we're going to separate out the display. Even though there is only one instance of the display, it's 
OK to turn it into a class:</p>
<example extract="false" title="Placing display in a library">
<b>calculator_display.lzx:</b>
<em>&lt;library&gt;</em>
  &lt;resource name="calc_display" src="../resources/display.png"/&gt;
  
  &lt;!-- The calculator display --&gt;
  &lt;<em>class name="calcDisplay"</em> resource="calc_display" x="20" y="31"
            oninit="this.start()"&gt;
    &lt;!-- the text in the display --&gt;
    &lt;text name="screen" height="30" width="165"
                font="displayText" fontsize="30"
                y="5" x="5"&gt;
      0
    &lt;/text&gt;
    
    &lt;method name="start"&gt;
      this.valueX = 0;
      this.lastInput = 'none';
      this.oldValue = false;
      this.allOperators = new array('+', '-', '/', '*');
      this.operator = '+';
      this.screen.setText(this.valueX.toString());
    &lt;/method&gt;
    
    &lt;method name="clear"&gt;
      this.start();
    &lt;/method&gt;
    
    &lt;!-- handles the push of a button --&gt;
    &lt;method name="inputDigit" args="buttonObj"&gt;
    &lt;![CDATA[
      var val = buttonObj.buttonText.getText();
      // weed out any non-numbers (e.g. operators, clear button)
      if (isInArray(val, this.allOperators)) {
        var theOperator = val;
        this.inputOperator(theOperator);
        return;
      } else if (val == 'C') {
        this.start();
        return;
      } else if (val == '.') {
        this.addDecimalPoint();
        return;
      } else if (val == '+/-') {
        this.negative();
        return;
      } else if (val == '=') {
        this.equals();
        return;
      }
      displ = this.screen.getText();
      if ((displ == '0') &amp;&amp; (val == '0')) {
        return;
      }
      if ((this.lastInput == 'none') 
          || (this.lastInput == 'operator')) {
        // clear display and rewrite
        this.screen.setText(val);    
      } else if (this.lastInput == 'digit') {
        this.screen.setText(displ + val);
      } else if (this.lastInput == 'equals') {
        this.clear();
        this.screen.setText(val);
      }
      this.lastInput = 'digit';
    ]]&gt;
    &lt;/method&gt;
    
    &lt;method name="inputOperator" args="operator"&gt;
      if (this.lastInput == 'digit') {
        this.execute(this.screen.getText());
      }
      this.valueX = this.screen.getText();
      this.operator = operator;
      this.lastInput = 'operator';
    &lt;/method&gt;
    
    &lt;method name="equals"&gt;
      if (this.lastInput != 'equals') {
        this.oldValue = this.screen.getText();
        this.lastInput = 'equals';
        this.execute(this.oldValue);
      } else {
        this.lastInput = 'equals';
        this.execute(this.oldValue);
      }
    &lt;/method&gt;
    
    &lt;method name="execute" args="val"&gt;
      this.valueX -= 0;
      var valFromDisp = val - 0;
      if (this.valueX == 0) return;
      if (this.operator == '+') {
        val = this.valueX + valFromDisp;
      } else if (this.operator == '-') {
        val = this.valueX - valFromDisp;
      } else if (this.operator == '*') {
        val = this.valueX * valFromDisp;
      } else if (this.operator == '/') {
        val = this.valueX / valFromDisp;
      }
      valFromDisp = val;
      this.screen.setText(valFromDisp.toString());
      this.valueX = this.screen.getText();
    &lt;/method&gt;
    
    &lt;method name="isThereDecimal"&gt;
    &lt;![CDATA[
      var disp = this.screen.getText();
      var isDecimal = false;
      for (var i=0; i != disp.length; i++) {
        if (disp.charAt(i) == '.') {
            return true;
        }
      }
      return false;
  ]]&gt;
    &lt;/method&gt;
    
    &lt;method name="addDecimalPoint"&gt;
      if ((this.lastInput == 'none') 
          || (this.lastInput == 'operator')) {
        if (!this.isThereDecimal()) {
            this.screen.setText("0.");
        }
      } else if (this.lastInput == 'digit') {
        if (!this.isThereDecimal()) {
            var newText = this.screen.getText();
            newText += ".";
            this.screen.setText(newText);
        }
      } else if (this.lastInput == 'equals') {
        this.clear(); 
        this.screen.setText('0.');
      }
      this.lastInput = 'digit';
    &lt;/method&gt;
    
    &lt;method name="negative"&gt;
      if ((this.lastInput == 'digit') ||
          (this.lastInput == 'equals')) {
        var newDisp = (this.screen.getText() - 0) * -1;
        this.screen.setText(newDisp.toString()); 
      } else {
        clear();
      }            
    &lt;/method&gt;
  &lt;/class&gt;
<em>&lt;/library&gt;</em>
</example>
<p>The <tagname>view</tagname> tag changes to a <tagname>class</tagname> tag, and the id attribute is removed. This is because if
 we used an id attribute here (i.e. in the <i>class definition</i>, then every instance of that class would have the same 
id (which would cause problems, since IDs are supposed to be unique!). We also added a <attribute>name</attribute> attribute, which will get used to create 
instances of the class. The resource for the display is also included in the display library file.</p>
<p>Finally, the code for the calculator itself:</p>
<example title="Calculator implemented with libraries">
&lt;canvas width="800" height="400"&gt;
  &lt;!-- fonts --&gt;
  &lt;font src="helmetbi.ttf" name="obliqueText"/&gt;
  &lt;font src="helmetr.ttf" name="displayText"/&gt;
  
  &lt;!-- art assets --&gt;
  &lt;resource name="calc_body" src="../resources/body.png"/&gt;
  
  &lt;!-- includes --&gt;
  <em>&lt;include href="../calculator_button.lzx"/&gt;
  &lt;include href="../calculator_display.lzx"/&gt;</em>
  
  &lt;!-- global variables and functions --&gt;
  &lt;script&gt;
  &lt;![CDATA[
        // utility function that finds an item in an array
        //
        function isInArray(x, theArray) {
            var isThere = false;
            for (var i=0; i&lt;theArray.length; i++) {
                if (theArray[i] == x) {
                    isThere = true;
                }
            }
            return isThere;
        }
  ]]&gt;
  &lt;/script&gt;
  
  &lt;view name="calculator" resource="calc_body" x="20" y="20"&gt;
    &lt;!-- display --&gt;
    <em>&lt;calcDisplay id="display"/&gt;</em>
      &lt;!-- 5 rows of buttons --&gt;
      &lt;view name="buttons" x="19" y="88"&gt;
        &lt;simplelayout axis="y" spacing="7"/&gt;
        
        &lt;!-- row 1 --&gt;
        &lt;view name="row1" width="100%"&gt;
          &lt;calcButton buttLabel="C" resource="button_red"/&gt;
          &lt;calcButton buttLabel="/" align="right" labelX="13"/&gt;
        &lt;/view&gt;
        
        &lt;!-- row 2 --&gt;
        &lt;view name="row2"&gt;
          &lt;simplelayout axis="x" spacing="7"/&gt;
          &lt;calcButton buttLabel="7"/&gt;
          &lt;calcButton buttLabel="8"/&gt;
          &lt;calcButton buttLabel="9"/&gt;
          &lt;calcButton buttLabel="*" labelX="13"/&gt;
        &lt;/view&gt;
        
        &lt;!-- row 3 --&gt;
        &lt;view name="row3"&gt;
          &lt;simplelayout axis="x" spacing="7"/&gt;
          &lt;calcButton buttLabel="4"/&gt;
          &lt;calcButton buttLabel="5"/&gt;
          &lt;calcButton buttLabel="6"/&gt;
          &lt;calcButton buttLabel="-" labelX="15"/&gt;
        &lt;/view&gt;
        
        &lt;!-- row 4 --&gt;
        &lt;view name="row4"&gt;
          &lt;simplelayout axis="x" spacing="7"/&gt;
          &lt;calcButton buttLabel="1"/&gt;
          &lt;calcButton buttLabel="2"/&gt;
          &lt;calcButton buttLabel="3"/&gt;
          &lt;calcButton buttLabel="+"/&gt;
        &lt;/view&gt;
        
        &lt;!-- row 5 --&gt;
        &lt;view name="row5"&gt;
          &lt;simplelayout axis="x" spacing="7"/&gt;
          &lt;calcButton buttLabel="0"/&gt;
          &lt;calcButton buttLabel="+/-" labelX="1"/&gt;
          &lt;calcButton buttLabel="." labelX="16"/&gt;
          &lt;calcButton buttLabel="=" resource="button_grn" labelX="12"/&gt;
        &lt;/view&gt;
      &lt;/view&gt;
  &lt;/view&gt;
&lt;/canvas&gt;
</example>
<p>We used the same id attribute that we had in the <tagname>view</tagname> tag of the display in the <i>instance</i> of the calcDisplay class.
The calculator app is now broken up across three files:</p>
<ol>
  <li>calculator_main.lzx</li>
  <li>calculator_display.lzx</li>
  <li>calculator_display.lzx</li>
</ol>
<p>At the very least, classes help minimize the amount of typing you have to do, as well as giving you an intuitive system 
for dividing up and organizing your code. LZX was designed to be an Object Oriented language, and the use of classes in LZX goes much 
further than saving you typing. </p>
<p>For a deeper discussion of using classes in LZX, see the <xref linkend="introductory-classes">Classes</xref> and 
<xref linkend="classes-inheritance">Extending Classes</xref>
chapters of the Guide</p>
<!-- lz_content_end -->

<!-- * H_LZ_COPYRIGHT_BEGIN *********************************************** -->
<p class="copyright">Copyright &#xA9; 2002-2005 <a target="_top"
href="http://www.laszlosystems.com/">Laszlo Systems, Inc.</a>
All Rights Reserved. Unauthorized use, duplication or
distribution is strictly prohibited. This is the proprietary
information of Laszlo Systems, Inc. Use is subject to license terms.</p>
<!-- * H_LZ_COPYRIGHT_END ************************************************* -->
</body>
</html>

